home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / genutils.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  39KB  |  1,577 lines

  1. /*
  2.  * @(#)genutils.c    1.11  1/20/89
  3.  */
  4. #include "assert.h"
  5. #include "addresses.h"
  6. #include "nodes.h"
  7. #include "map.h"
  8. #include "sequence.h"
  9. #include "system.h"
  10. #include "builtins.h"
  11. #include "evaluate.h"
  12. #include "opNames.h"
  13. #include "primitives.h"
  14. #include "allocate.h"
  15. #include "MyParser.h"
  16. #include "datadesc.h"
  17. #include "environment.h"
  18. #include "regdefs.h"
  19. #include "genutils.h"
  20. #include "scan.h"
  21. #include "semantics.h"
  22. #include "emit.h"
  23. #include "trace.h"
  24. #include "flags.h"
  25. #include "option.h"
  26.  
  27. /*
  28.  * Utility routines for writing to the code file.
  29.  */
  30.  
  31. char *junk = "junk";
  32. #ifdef vax
  33. char *registerName[] = {
  34.   "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
  35.   "r8",  "r9",  "r10", "r11", "r12", "r13", "sp",  "pc",  "junk"
  36. };
  37. #endif
  38. #ifdef sun
  39. char *registerName[] = {
  40.   "a0",  "a1",  "d0",  "d1",  "a2",  "a3",  "d2",  "d3",
  41.   "d4",  "d5",  "d6",  "a4",  "a5",  "a6",  "sp",  "pc",  "junk"
  42. };
  43. #endif
  44.  
  45. typedef struct sHSEntry {
  46.   NodePtr         p;
  47.   int             startlabel;
  48.   int             fhlabel;
  49.   int             belabel;
  50.   int             loopexitlabel;
  51.   struct sBEntry    *parent;
  52.   struct sHSEntry    *next;
  53. } HSEntry, *HSEntryPtr;
  54. static HSEntryPtr HSStackTop = NULL;
  55.  
  56. typedef struct sBEntry {
  57.   int             bslabel;
  58.   int             uhlabel;
  59.   int             fhlabel;
  60.   int             belabel;
  61.   struct sBEntry    *parent;
  62. } BEntry, *BEntryPtr;
  63. static BEntryPtr BStackTop = NULL;
  64.  
  65. Boolean wroteCode;
  66.  
  67. static int lastLineNumber;
  68. IPMapCollectorPtr lineNumberMap;
  69. IPMapCollectorPtr unavailableHandlerMap;
  70. IPMapCollectorPtr failureHandlerMap;
  71.  
  72. void initializeMaps()
  73. {
  74.   int label = nextLabelNumber++;
  75.   
  76.   lastLineNumber = -1;
  77.   wroteCode = FALSE;
  78.   if (! doGenerateCode) {
  79.     failureHandlerMap = createIPMap(label);
  80.     unavailableHandlerMap = createIPMap(label);
  81.     lineNumberMap = createIPMap(label);
  82.   }
  83.   BStackTop = NULL;
  84.   emit("L_%d:\n", label);
  85. }
  86.  
  87. void forceLineNumber()
  88. {
  89.   lastLineNumber = -1;
  90. }
  91.  
  92. void lineNumberComment(p)
  93. NodePtr p;
  94. {
  95.   int label;
  96.   if ((lastLineNumber == -1 || wroteCode) && lastLineNumber != p->lineNumber){
  97.     label = nextLabelNumber++;
  98.     emit("L_%d:\t", label);
  99.     if (gtflag) {
  100. #ifdef vax
  101.       emit("blbc\t*$ _emTracing,1f\n");
  102. #endif
  103. #ifdef sun
  104.       emit("tstl\t_emTracing\n");
  105.       emit("\tbeq\t1f\n");
  106. #endif
  107.       emit("\tj%s\t%s_em_trace\n", JN(SUBR), GLOBALVARINDICATOR);
  108.       emit("1:\t");
  109.     }
  110.     if (lastLineNumber > 0)
  111.       addToIPMap(&lineNumberMap, label, -1, lastLineNumber);
  112.     Comment("\t\t\t\t\"%s\", line %d", currentFileName, p->lineNumber);
  113.     TRACE1(linenumber, 1, "Line number %d", p->lineNumber);
  114.   }
  115.   lastLineNumber = p->lineNumber;
  116.   wroteCode = FALSE;
  117. }
  118.  
  119. void finalizeMaps()
  120. {
  121.   int label = nextLabelNumber++;
  122.   emit("L_%d:\n", label);
  123.   addToIPMap(&failureHandlerMap, label, -1, 0);
  124.   addToIPMap(&unavailableHandlerMap, label, -1, 0);
  125.   addToIPMap(&lineNumberMap, label, -1, lastLineNumber);
  126. }
  127.  
  128. Boolean mapHasEntries(m)
  129. register IPMapCollectorPtr m;
  130. {
  131.   if (m->nextToFill == 0) return(FALSE);
  132.   if (m->nextToFill == 1 && m->entry[0].dataLabel < 0 && m->entry[0].value == 0)
  133.     return(FALSE);
  134.   return(TRUE);
  135. }
  136.  
  137. void dumpMaps()
  138. {
  139.   if (! doGenerateCode) return;
  140.   if (mapHasEntries(failureHandlerMap)) {
  141.     emit("L_failureHandlerMap:\n");
  142.     dumpIPMap(failureHandlerMap);
  143.   }
  144.   if (mapHasEntries(unavailableHandlerMap)) {
  145.     emit("L_unavailableHandlerMap:\n");
  146.     dumpIPMap(unavailableHandlerMap);
  147.   }
  148.   if (mapHasEntries(lineNumberMap)) {
  149.     emit("L_lineNumberMap:\n");
  150.     dumpIPMap(lineNumberMap);
  151.   }
  152. }
  153.  
  154. extern int indexSize;
  155.  
  156. char *addressToString(a)
  157. Address a;
  158. {
  159.   static char buffer[32];
  160.   if (a.base == Register) {
  161.     sprintf(buffer, "%s", RN(a.offset));
  162.   } else if (a.autoDecrement || a.autoIncrement) {
  163.     assert(a.offset == 0);
  164.     assert(! (a.autoDecrement && a.autoIncrement));
  165. #ifdef vax
  166.     sprintf(buffer, "%s(%s)%s", 
  167.       a.autoDecrement ? "-" : "",
  168.       RN(a.base),
  169.       a.autoIncrement ? "+" : "");
  170. #endif
  171. #ifdef sun
  172.       sprintf(buffer, "%s@%s", RN(a.base), a.autoDecrement ? "-" : "+");
  173. #endif
  174.   } else {
  175.     if (a.hasIndex) {
  176. #ifdef vax
  177.       sprintf(buffer, "%d(%s)[%s]", a.offset, RN(a.base), RN(a.indexReg));
  178. #endif
  179. #ifdef sun
  180.       assert(indexSize > 0);
  181.       if (indexSize == 1) {
  182.     sprintf(buffer, "%s@(%d,%s:l)", RN(a.base), a.offset, RN(a.indexReg));
  183.       } else {
  184.     sprintf(buffer, "%s@(%d,%s:l:%d)", RN(a.base), a.offset, RN(a.indexReg), indexSize);
  185.       }
  186. #endif
  187.     } else if (a.offset == 0) {
  188. #ifdef vax
  189.       sprintf(buffer, "(%s)", RN(a.base));
  190. #endif
  191. #ifdef sun
  192.       sprintf(buffer, "%s@", RN(a.base));
  193. #endif
  194.     } else {
  195. #ifdef vax
  196.       sprintf(buffer, "%d(%s)", a.offset, RN(a.base));
  197. #endif
  198. #ifdef sun
  199.       sprintf(buffer, "%s@(%d)", RN(a.base), a.offset);
  200. #endif
  201.     }
  202.   }
  203.   return(buffer);
  204. }
  205.  
  206. DD nullDD, pusher, popper, nilDD;
  207. NodePtr nilNode;
  208. Context anyContext, pslContext, pusherContext;
  209.  
  210. Boolean DDNeedsLabel(d)
  211. DD d;
  212. {
  213.   return(d.kind == DD_OIDToODP || d.kind == DD_OIDToODAP ||
  214.      d.kind == DD_AbCon || d.kind == DD_OIDToCodePtr);
  215. }
  216.  
  217. #define abs(N) ((N) < 0 ? (-(N)) : (N))
  218.  
  219. void writeLabel(d, c)
  220. DD d;
  221. char c;
  222. {
  223.   assert(d.kind == DD_Label);
  224.   if (d.value.label < 100) {
  225.     emit("%d%c", abs(d.value.label),
  226.       d.value.label < 0 ? 'b' : 'f');
  227.   } else {
  228.     emit("L_%d", d.value.label);
  229.   }
  230.   if (c != '\0') (void) emit("%c", c);
  231. }
  232.  
  233. extern Boolean formatAs0r;
  234.  
  235. void writeDD(d, c)
  236. DD d;
  237. char c;
  238. {
  239.   NodePtr p;
  240.   wroteCode = TRUE;
  241.   switch (d.kind) {
  242.     case DD_Label:
  243. #ifdef sun
  244.       emit("pc@(");
  245. #endif
  246.       if (d.value.label < 100) {
  247.     emit("%d%c", abs(d.value.label), d.value.label < 0 ? 'b' : 'f');
  248.       } else {
  249.     emit("L_%d", d.value.label);
  250.       }
  251. #ifdef sun
  252.       emit("-.-2:l)");
  253. #endif
  254.       break;
  255.     case DD_Address:
  256.       emit(addressToString(d.value.address));
  257.       break;
  258.     case DD_Manifest:
  259.       if (d.value.manifest & 0xc0000000) {
  260.     emit("%c0x%08x", IMMEDIATECHAR, d.value.manifest);
  261.       } else {
  262.     emit("%c%d", IMMEDIATECHAR, d.value.manifest);
  263.       }
  264.       break;
  265.     case DD_RealManifest:
  266. #ifdef vax
  267.       emit("%c0f%s", IMMEDIATECHAR, d.value.realmanifest);
  268. #endif
  269. #ifdef sun
  270.       if (formatAs0r) {
  271.     emit("%c0r%s", IMMEDIATECHAR, d.value.realmanifest);
  272.       } else {
  273.     float f;
  274.     double atof();
  275.     f = atof(d.value.realmanifest);
  276.     emit("%c0x%08x", IMMEDIATECHAR, (* ((int *)&f)));
  277.       }
  278. #endif
  279.       break;
  280.     case DD_PSLCondition:
  281.       assert(FALSE);
  282.       break;
  283.     case DD_OIDToODP:
  284.       emit("%c0xabcdef01", IMMEDIATECHAR);
  285.       p = OTLookup(d.value.id);
  286.       assert(p != NULL);
  287.       if (p->tag == P_OBLIT) {
  288.     if (!bflag) ensureGenerate(getCodeOID(p));
  289.     if (p->b.oblit.f.immutable) {
  290.       saveRelocationInfo(currentInstruction, 2, AR_OIDToODAP, d.value.id,
  291.         getCodeOID(p));
  292.     } else if (Zflag) {
  293.       saveRelocationInfo(currentInstruction, 2, AR_OIDToCheatingODP, d.value.id,
  294.         getCodeOID(p));
  295.     } else {
  296.       saveRelocationInfo(currentInstruction, 2, AR_OIDToODP, d.value.id,
  297.         getCodeOID(p));
  298.     }
  299.       } else {
  300.     assert(p->tag == P_ATLIT);
  301.     saveRelocationInfo(currentInstruction, 2, AR_OIDToODP, d.value.id,
  302.       OIDOfBuiltin(B_INSTCT, SIGNATUREINDEX));
  303.       }
  304.       break;
  305.     case DD_OIDToODAP:
  306.       emit("%c0xabcdef01", IMMEDIATECHAR);
  307.       saveRelocationInfo(currentInstruction, 2, AR_OIDToODAP, d.value.id, 0);
  308.       break;
  309.     case DD_OIDToCodePtr:
  310.       emit("%c0xabcdef01", IMMEDIATECHAR);
  311.       saveRelocationInfo(currentInstruction, 2, AR_OIDToCodePtr, d.value.id, 0);
  312.       break;
  313.     case DD_AbCon:
  314.       emit("%c0xabcdef01", IMMEDIATECHAR);
  315.       ensureGenerate(getDDAbstractType(d));
  316.       if (!bflag) ensureGenerate(getDDConcreteType(d));
  317.       saveRelocationInfo(currentInstruction, 2, AR_OIDOIDToAbCon,
  318.     getDDAbstractType(d), getDDConcreteType(d));
  319.       break;
  320.     default:
  321.       assert(FALSE);
  322.       break;
  323.   }
  324.   if (c != '\0') (void) emit("%c", c);
  325. }
  326.  
  327. void debugDD(d)
  328. DD d;
  329. {
  330.   displayDD(stdout, d, '\n');
  331.   fflush(stdout);
  332. }
  333.  
  334. void displayDD(f, d, c)
  335. FILE *f;
  336. DD d;
  337. char c;
  338. {
  339.   switch (d.kind) {
  340.     case DD_Label:
  341. #ifdef sun
  342.       emit("pc@(");
  343. #endif
  344.       if (d.value.label < 100) {
  345.     fprintf(f, "%d%c", abs(d.value.label),
  346.       d.value.label < 0 ? 'b' : 'f');
  347.       } else {
  348.     fprintf(f, "L_%d", d.value.label);
  349.       }
  350. #ifdef sun
  351.       emit("-.-2)");
  352. #endif
  353.       break;
  354.     case DD_Address:
  355.       fprintf(f, addressToString(d.value.address));
  356.       if (d.value.address.baseIsTemporary) {
  357.     if (d.value.address.base == Register) {
  358.       fprintf(f, " (t%s)", RN(d.value.address.offset));
  359.     } else if (d.value.address.base == regs_l) {
  360.       /* this really means free the temp stack storage */
  361.       fprintf(f, " (ts%d)", d.value.address.offset);
  362.     } else {
  363.       fprintf(f, " (t%s)", RN(d.value.address.base));
  364.     }
  365.       }
  366.       if (d.value.address.indexIsTemporary) {
  367.     fprintf(f, " (ti %s)", RN(d.value.address.indexReg));
  368.       }
  369.       break;
  370.     case DD_Manifest:
  371.       if (d.value.manifest & 0xc0000000) {
  372.     fprintf(f, "%c0x%08x", IMMEDIATECHAR, d.value.manifest);
  373.       } else {
  374.     fprintf(f, "%c%d", IMMEDIATECHAR, d.value.manifest);
  375.       }
  376.       break;
  377.     case DD_RealManifest:
  378. #ifdef vax
  379.       fprintf(f, "%c0f%s", IMMEDIATECHAR, d.value.realmanifest);
  380. #endif
  381. #ifdef sun
  382.       if (formatAs0r) {
  383.     fprintf(f, "%c0r%s", IMMEDIATECHAR, d.value.realmanifest);
  384.       } else {
  385.     float fl;
  386.     double atof();
  387.     fl = atof(d.value.realmanifest);
  388.     fprintf(f, "%c0x%08x", IMMEDIATECHAR, (* ((int *)&fl)));
  389.       }
  390. #endif
  391.       break;
  392.     case DD_PSLCondition:
  393.       fprintf(f, "psl %s", JN(d.value.condition.psl));
  394.       break;
  395.     case DD_OIDToODP:
  396.       fprintf(f, "OIDToODP 0x%08x", d.value.id);
  397.       break;
  398.     case DD_OIDToODAP:
  399.       fprintf(f, "OIDToODAP 0x%08x", d.value.id);
  400.       break;
  401.     case DD_OIDToCodePtr:
  402.       fprintf(f, "OIDToCodePtr 0x%08x", d.value.id);
  403.       break;
  404.     case DD_AbCon:
  405.       fprintf(f, "DD_AbCon 0x%08x 0x%08x",
  406.     getDDAbstractType(d), getDDConcreteType(d));
  407.       break;
  408.     default:
  409.       fprintf(f, "JUNK!");
  410.       break;
  411.   }
  412.   if (c == '\n' && d.kind != DD_AbCon) {
  413.     fprintf(f, " AT = 0x%08x\n", getDDAbstractType(d));
  414.   } else if (c != '\0') (void) fputc(c, f);
  415. }
  416.  
  417. void generateKernelCall(opName)
  418. char *opName;
  419. {
  420.   Boolean checkJump;
  421.   if (!strcmp(opName, "em_stackCheck") ||
  422.       !strcmp(opName, "ems_compare") ||
  423.       !strcmp(opName, "emtime_compare") ||
  424.       !strcmp(opName, "em_invokeAssumptionFailure")) checkJump = FALSE;
  425.   else checkJump = TRUE;
  426.   if (checkJump) JUMPDEBUG();
  427.   emit("\tj%s\t%s_%s\n", JN(SUBR), GLOBALVARINDICATOR, opName);
  428.   if (checkJump) JUMPCHECK();
  429. }
  430.  
  431. void writeData(n)
  432. int n;
  433. {
  434.   emit("\t.long\t%d\n", n);
  435. }
  436.  
  437. void writeWord(n)
  438. int n;
  439. {
  440.   emit("\t.word\t%d\n", n);
  441. }
  442.  
  443. void writeHex(n)
  444. OID n;
  445. {
  446.   emit("\t.long\t0x%.8x\n", n);
  447. }
  448.  
  449. void writeHexComment(n, c)
  450. OID n;
  451. char *c;
  452. {
  453.   emit("\t.long\t0x%.8x", n);
  454.   Comment(c);
  455. }
  456.  
  457. static ODTag nullTag;
  458.  
  459. ODTag BuildTag(fBasicTag, fReplicated)
  460. ODBasicTag fBasicTag;
  461. Boolean fReplicated;
  462. {
  463.   register ODTag t;
  464.   t = nullTag;
  465.   t.otherstuff = OBSCUREVALUE;
  466.   t.tag = fBasicTag;
  467.   t.replicated = fReplicated;
  468.   if (t.tag == GODataTag && fReplicated) {
  469.     /* We introduced LOTag to handle local objects, and at the moment, 
  470.      * replicated objects are local.
  471.      */
  472.     t.tag = LOTag;
  473.   }
  474.   return(t);
  475. }
  476.  
  477. /*
  478.  * The IP to Template map is generated on the basis of well known names.  
  479.  * All we need is the number of routines, and whether the initially,
  480.  * process, and recovery sections exist.
  481.  */
  482.  
  483. /*
  484.  * The IPToLineNumber, IP to UnavailableHandler, and IP to FailureHandler
  485.  * maps are saved as code is generated.  The failure and unavailable handler
  486.  * maps require a stack as they nest.  The line number map is simple.
  487.  */
  488. #define NEWIPMAPCOLLECTOR(N) ((IPMapCollectorPtr) malloc(sizeof(IPMapCollector) +\
  489.   ((N)-1)*3*sizeof(int)))
  490.  
  491. IPMapCollectorPtr createIPMap(lowCodeLabel)
  492. int lowCodeLabel;
  493. {
  494.   register IPMapCollectorPtr p;
  495.   p = NEWIPMAPCOLLECTOR(10);
  496.   p->maxSize = 10;
  497.   p->nextToFill = 0;
  498.   p->lowCodeLabel = lowCodeLabel;
  499.   return(p);
  500. }
  501.  
  502. void addToIPMap(p, codeLabel, dataLabel, value)
  503. IPMapCollectorPtr *p;
  504. int codeLabel, dataLabel, value;
  505. {
  506.   register IPMapCollectorPtr lp = *p;
  507.   register int index;
  508.   register IPMapCEntryPtr ipme;
  509.   
  510.   if (doGenerateCode) return;
  511.   if (lp->nextToFill == 0) {
  512.     if (dataLabel < 0 && value == 0) {
  513.       /* this is a non-existant first entry */
  514.       lp->lowCodeLabel = codeLabel;
  515.       return;
  516.     }
  517.   } else {
  518.      ipme = &lp->entry[lp->nextToFill - 1];
  519.      if (ipme->dataLabel < 0 && dataLabel < 0) {
  520.     if (ipme->value == value) {
  521.       ipme->codeLabel = codeLabel;
  522.       return;
  523.     }
  524.      } else if (ipme->dataLabel == dataLabel) {
  525.     ipme->codeLabel = codeLabel;
  526.     return;
  527.      }
  528.   }
  529.   if (lp->nextToFill >= lp->maxSize) {
  530.     IPMapCollectorPtr np;
  531.     register int i;
  532.     np = NEWIPMAPCOLLECTOR((unsigned)2 * lp->maxSize);
  533.     np->maxSize = 2 * lp->maxSize;
  534.     np->nextToFill = lp->nextToFill;
  535.     np->lowCodeLabel = lp->lowCodeLabel;
  536.     for (i = 0; i < lp->maxSize; i++) {
  537.       np->entry[i] = lp->entry[i];
  538.     }
  539.     free((char *)lp);
  540.     *p = np;
  541.     lp = np;
  542.   }
  543.   index = lp->nextToFill;
  544.   lp->entry[index].codeLabel = codeLabel;
  545.   lp->entry[index].dataLabel = dataLabel;
  546.   lp->entry[index].value = value;
  547.   lp->nextToFill++;
  548. }
  549.  
  550. void dumpIPMap(p)
  551. register IPMapCollectorPtr p;
  552. {
  553.   register int i;
  554.   i = p->nextToFill - 1;
  555.   if (i >= 0 && p->entry[i].dataLabel < 0 && p->entry[i].value == 0) {
  556.     i--;
  557.     p->nextToFill --;
  558.   }
  559.   if (p->nextToFill > 0) {
  560.     emit("\t.long\tL_%d - L_beginCDA\n",
  561.       i >= 0 ? p->entry[i].codeLabel : p->lowCodeLabel);
  562.     emit("\t.long\tL_%d - L_beginCDA\n", p->lowCodeLabel);
  563.     for (i = 0; i < p->nextToFill; i++) {
  564.       emit("\t.long\tL_%d - L_beginCDA\n", p->entry[i].codeLabel);
  565.       if (p->entry[i].dataLabel >= 0) {
  566.     emit("\t.long\tL_%d - L_beginCDA\n", p->entry[i].dataLabel);
  567.       } else {
  568.     writeData(p->entry[i].value);
  569.       }
  570.     }
  571.   }
  572.   if (doGenerateCode) free((char *) p);
  573. }
  574.  
  575. /*
  576.  * The op vector is also done on the basis of well known names.
  577.  */
  578.  
  579. /*
  580.  * Utility routines for saving relocation information and eventual writing to
  581.  * the code file.
  582.  */
  583. static RelocationInfoPtr relocPtr;
  584. static unsigned int relocationSize;
  585.  
  586. void initializeRelocationInfo()
  587. {
  588. # define MINIMUMSIZE 50
  589.   relocPtr = NEWRelocationInfo(MINIMUMSIZE);
  590.   relocPtr->numEntries = 0;
  591.   relocationSize = MINIMUMSIZE;
  592. # undef MINIMUMSIZE
  593. }
  594.  
  595. void saveRelocationInfo(labelNumber, offset, kind, OID1, OID2)
  596. int labelNumber, offset;
  597. AR_Kind kind;
  598. OID OID1, OID2;
  599. {
  600.   register RelocationInfoPtr np;
  601.   register int i;
  602.   if (relocPtr->numEntries >= relocationSize) {
  603.     relocationSize *= 2;
  604.     np = NEWRelocationInfo(relocationSize);
  605.     np->numEntries = relocPtr->numEntries;
  606.     for (i = 0; i < relocPtr->numEntries; i++) {
  607.       np->relocation[i] = relocPtr->relocation[i];
  608.     }
  609.     free((char *) relocPtr);
  610.     relocPtr = np;
  611.   }
  612.   i = relocPtr->numEntries++;
  613.   relocPtr->relocation[i].kind = kind;
  614.   relocPtr->relocation[i].where = (labelNumber << 8) + offset;
  615.   relocPtr->relocation[i].theOID1 = OID1;
  616.   relocPtr->relocation[i].theOID2 = OID2;
  617. }
  618.  
  619. void dumpRelocationInfo()
  620. {
  621.   register int i;
  622.   register ARelocationPtr ar;
  623.   register int label, offset;
  624.   
  625.   emit("L_relocInfoStart:\n");
  626.   writeData(relocPtr->numEntries);
  627.   for (i = 0; i < relocPtr->numEntries; i++) {
  628.     ar = &relocPtr->relocation[i];
  629.     label = (ar->where >> 8) & 0xffff;
  630.     offset = (ar->where) & 0xff;
  631. #ifdef vax
  632.     emit("\t.long\t((L_%d-L_beginCDA+%d)<<8)+%d\n",
  633.       label, offset, (int) ar->kind);
  634. #else
  635. #ifdef sun
  636.     emit("\t.long\t(L_%d-L_beginCDA+%d)+((%d)*%d)\n",
  637.       label, offset, (int) ar->kind, 1<<24);
  638. #endif
  639. #endif
  640.     writeHex(ar->theOID1);
  641.     writeHex(ar->theOID2);
  642.   }
  643.   free((char *) relocPtr);
  644.   relocPtr = NULL;
  645. }
  646.  
  647. /*
  648.  * Utility routines for saving templates for eventual output to the code file.
  649.  */
  650.  
  651. typedef struct sTemplateDescription {
  652.   char            *name;
  653.   int              number;
  654.   TemplatePtr         tp;
  655. } TemplateDescription, *TemplateDescriptionPtr;
  656.  
  657. typedef struct sTDC {
  658.   int             numEntries;
  659.   TemplateDescription     td[12];
  660. } TDC, *TDCPtr;
  661. #define NEWTDC(N) ((TDCPtr) malloc(\
  662.   (unsigned) (sizeof(TDC) -\
  663.   12 * sizeof(TemplateDescription) +\
  664.   (N) * sizeof(TemplateDescription))))
  665.  
  666. static TDCPtr tdcPtr;
  667. static int TDCSize;
  668.  
  669. static TemplatePtr tempPtr;
  670. static unsigned int templateSize;
  671.  
  672. void initializeTemplates()
  673. {
  674. # define MINIMUMSIZE 50
  675.   tdcPtr = NEWTDC(MINIMUMSIZE);
  676.   TDCSize = MINIMUMSIZE;
  677.   tdcPtr->numEntries = 0;
  678. # undef MINIMUMSIZE
  679. }
  680.  
  681. extern char *strdup();
  682.  
  683. void setHasInvokeQueueBit(hasInvokeQueue)
  684. Boolean hasInvokeQueue;
  685. {
  686.   tdcPtr->td[tdcPtr->numEntries-1].tp->B.hasInvokeQueue = hasInvokeQueue;
  687. }
  688.  
  689. void initializeTemplate(name, number, exclusiveAccess)
  690. char *name;
  691. int number;
  692. Boolean exclusiveAccess;
  693. {
  694.   register TDCPtr np;
  695.   register int i;
  696.   name = strdup(name);
  697.   if (tdcPtr->numEntries >= TDCSize) {
  698.     TDCSize *= 2;
  699.     np = NEWTDC(TDCSize);
  700.     np->numEntries = tdcPtr->numEntries;
  701.     for (i = 0; i < tdcPtr->numEntries; i++) {
  702.       np->td[i] = tdcPtr->td[i];
  703.     }
  704.     free((char *) tdcPtr);
  705.     tdcPtr = np;
  706.   }
  707. # define MINIMUMSIZE 50
  708.   tempPtr = NEWTemplate(MINIMUMSIZE);
  709.   tempPtr->B.numEntries = 0;
  710.   templateSize = MINIMUMSIZE;
  711.   tdcPtr->td[tdcPtr->numEntries].name = name;
  712.   tdcPtr->td[tdcPtr->numEntries].number = number;
  713.   tdcPtr->td[tdcPtr->numEntries].tp = tempPtr;
  714.  
  715.   tempPtr->B.exclusiveAccess = exclusiveAccess;
  716.   tempPtr->B.hasInvokeQueue = FALSE;
  717.   tempPtr->B.notUsed = 0;
  718.   tdcPtr->numEntries++;
  719. # undef MINIMUMSIZE
  720. }
  721.  
  722. static void checkForRoomInTemplate()
  723. {
  724.   register TemplatePtr np;
  725.   register int i;
  726.   if (tempPtr->B.numEntries >= templateSize) {
  727.     templateSize *= 2;
  728.     np = NEWTemplate(templateSize);
  729.     np->B.numEntries = tempPtr->B.numEntries;
  730.     for (i = 0; i < tempPtr->B.numEntries; i++) {
  731.       np->entry[i] = tempPtr->entry[i];
  732.     }
  733.     free((char *) tempPtr);
  734.     tempPtr = np;
  735.     tdcPtr->td[tdcPtr->numEntries-1].tp = tempPtr;    
  736.   }
  737. }
  738.  
  739. void saveShortStaticTemplate(theBrand, paramInfo, elementBrand, count,
  740.   attachedFlag)
  741. Brand theBrand, elementBrand;
  742. ParamInfo paramInfo;
  743. int count;
  744. Boolean attachedFlag;
  745. {
  746.   register ShortStatic t, ot;
  747.   checkForRoomInTemplate();
  748.   if (tempPtr->B.numEntries > (unsigned)0) {
  749.     ot = tempPtr->entry[tempPtr->B.numEntries-1].TE.SS;
  750.     if (ot.Format == ShortStaticF &&
  751.     ot.theBrand == theBrand &&
  752.     ot.paramInfo == paramInfo &&
  753.     ot.elementBrand == elementBrand &&
  754.     ot.attachedFlag == attachedFlag) {
  755.       ot.count += count;
  756.       tempPtr->entry[tempPtr->B.numEntries-1].TE.SS = ot;
  757.       return;
  758.     }
  759.   }
  760.   t.Format = ShortStaticF;
  761.   t.theBrand = theBrand;
  762.   t.paramInfo = paramInfo;
  763.   t.attachedFlag = attachedFlag;
  764.   t.elementBrand = elementBrand;
  765.   t.count = count;
  766.   tempPtr->entry[tempPtr->B.numEntries].TE.SS = t;
  767.   tempPtr->B.numEntries++;
  768. }
  769.  
  770. void saveRegisterTemplate(theBrand, storedWhere, reg, count, attachedFlag)
  771. Brand theBrand;
  772. Placement storedWhere;
  773. int reg, count;
  774. Boolean attachedFlag;
  775. {
  776.   register RegisterTE t;
  777.   register RegisterTE ot;
  778.   checkForRoomInTemplate();
  779.   if (tempPtr->B.numEntries > (unsigned)0) {
  780.     ot = tempPtr->entry[tempPtr->B.numEntries-1].TE.R;
  781.     if (ot.Format == RegisterF &&
  782.     ot.theBrand == theBrand &&
  783.     ot.storedWhere == storedWhere &&
  784.     ot.attachedFlag == attachedFlag) {
  785.       ot.count += count;
  786.       tempPtr->entry[tempPtr->B.numEntries-1].TE.R = ot;
  787.       return;
  788.     }
  789.   }
  790.   t.Format = RegisterF;
  791.   t.theBrand = theBrand;
  792.   t.storedWhere = storedWhere;
  793.   t.attachedFlag = attachedFlag;
  794.   t.unusedFlag = FALSE;
  795.   t.reg = reg;
  796.   t.count = count;
  797.   tempPtr->entry[tempPtr->B.numEntries].TE.R = t;
  798.   tempPtr->B.numEntries++;
  799. }
  800.  
  801. extern char *brandNames[];
  802. char *ParamInfoNames[] = {
  803.   "",
  804.   "arg",
  805.   "res",
  806.   "moveres"
  807. };
  808.  
  809. void commentTemplate(t)
  810. register TemplateEntryPtr t;
  811. {
  812.   if (!doGenerateCode) return;
  813.   fprintf(codeFile, " %c ", COMMENTCHAR);
  814.  
  815.  
  816.   switch (t->TE.SS.Format) {
  817.     case ShortStaticF:
  818.       fprintf(codeFile,
  819.     "%3d %s%s %s", 
  820.     t->TE.SS.count,
  821.     t->TE.SS.attachedFlag ? "attached " : "",
  822.     ParamInfoNames[(int)t->TE.SS.paramInfo],
  823.     brandNames[(int)t->TE.SS.theBrand]);
  824.       if (t->TE.SS.theBrand == VectorBrand)
  825.     fprintf(codeFile, " of %s",
  826.       brandNames[(int)t->TE.SS.elementBrand]);
  827.       break;
  828.     case RegisterF:
  829.       fprintf(codeFile, "%sregister %s", 
  830.     t->TE.R.attachedFlag ? "attached " : "",
  831.     registerName[t->TE.R.reg]);
  832.       if (t->TE.R.count > 1)
  833.     fprintf(codeFile, " - %s", registerName[t->TE.R.reg+t->TE.R.count-1]);
  834.       fprintf(codeFile, " %s%s",
  835.     brandNames[(int)t->TE.R.theBrand],
  836.     t->TE.R.storedWhere == InRegister ? "" : " insavearea");
  837.       break;
  838.     default:
  839.       break;
  840.   }
  841.   (void) fputc('\n', codeFile);
  842. }
  843.  
  844. void dumpTemplate(name, number, tp)
  845. char *name;
  846. int number;
  847. TemplatePtr tp;
  848. {
  849.   register int i;
  850.   register TemplateEntryPtr te;
  851.   
  852.   emit(name, number);
  853.   emit(":\n");
  854.   writeTag(tp->B);
  855.   
  856.   for (i = 0; i < tp->B.numEntries; i++) {
  857.     te = &tp->entry[i];
  858.     switch (te->TE.SS.Format) {
  859.       case ShortStaticF:
  860.     writeTag(te->TE.SS);
  861.     break;
  862.       case RegisterF:
  863.     writeTag(te->TE.R);
  864.     break;
  865.       default:
  866.     assert(FALSE);
  867.     break;
  868.     }
  869.     commentTemplate(te);
  870.   }
  871.   free((char *) tp);
  872. }
  873.  
  874. void dumpTemplates()
  875. {
  876.   register int i;
  877.   register TemplateDescriptionPtr td;
  878.   
  879.   for (i = 0; i < tdcPtr->numEntries; i++) {
  880.     td = &tdcPtr->td[i];
  881.     dumpTemplate(td->name, td->number, td->tp);
  882.   }
  883.   free((char *) tdcPtr);
  884. }
  885.  
  886. int findATOpNumber(at, opName)
  887. NodePtr at, opName;
  888. {
  889.   register NodePtr sigs, asig, aname;
  890.   register OID theID;
  891.   
  892.   assert(at->tag == P_ATLIT);
  893.   assert(opName->tag == P_OPNAME);
  894.   theID = opName->b.opname.id;
  895.   sigs = at->b.atlit.ops;
  896.   assert(isASequence(sigs));
  897.   Sequence_For(asig, sigs)
  898.     assert(asig->tag == P_OPSIG);
  899.     aname = asig->b.opsig.name;
  900.     assert(aname->tag == P_OPNAME);
  901.     if (aname->b.opname.id == theID) return(z__z);
  902.   Sequence_Next
  903.   assert(FALSE);
  904.   /*NOTREACHED*/
  905. }
  906.  
  907. NodePtr resolveOIDToCTOrAT(id)
  908. OID id;
  909. {
  910.   register NodePtr p, q = NULL;
  911.   register OID codeoid;
  912.  
  913.   p = OTLookup(id);
  914.   assert((int)p != NIL);
  915.   if (p->tag == P_ATLIT) {
  916.     if (p->b.atlit.f.cannotBeConformedTo) {
  917.       codeoid = getCodeOID(p);
  918.       assert(codeoid != 0);
  919.       q = OTLookup(codeoid);
  920.       assert(q->tag == P_OBLIT);
  921.       assert(q != NULL);
  922.       p = q;
  923.     }
  924.   }
  925.   return(p);
  926. }
  927.  
  928. NodePtr resolveToCTOrAT(p)
  929. NodePtr p;
  930. {
  931.   Symbol st;
  932.   OID id;
  933.   NodePtr q;
  934.   switch (p->tag) {
  935.     case P_GLOBALREF:
  936.       resolveGlobal(p, (ValuePtr) NULL);
  937.       return(resolveToCTOrAT(p->b.globalref.value));
  938.       /* break; */
  939.     case P_OBLIT:
  940.       return(p);
  941.       /* break; */
  942.     case P_ATLIT:
  943.       id = getCodeOID(p);
  944.       if (id != 0) {
  945.     q = OTLookup(id);
  946.     assert((int)q != NIL);
  947.     return(q);
  948.       } else if (p->b.atlit.f.writeSeparately) {
  949.     assert(p->b.atlit.id != 0);
  950.     return(resolveOIDToCTOrAT(p->b.atlit.id));
  951.       } else {
  952.     return(p);
  953.       }
  954.       /* break; */
  955.     case P_SYMREF:
  956.       st = ST_Fetch(p->b.symref.symbol);
  957.       assert(st->isManifest);
  958.       assert(st->value.value != NULL);
  959.       return(resolveToCTOrAT(st->value.value));
  960.       /* break; */
  961.     default:
  962.       assert(FALSE);
  963.       /*NOTREACHED*/
  964.       /* break; */
  965.   }
  966. }
  967.  
  968. /*
  969.  * Return the best description of the entity that will result by executing
  970.  * the expression.
  971.  */
  972. NodePtr getBestInfoFromExpression(p)
  973. register NodePtr p;
  974. {
  975.   Symbol st;
  976.   assert ((int)p > 0x200);
  977.   switch (p->tag) {
  978.     case P_BUILTINLIT:
  979.       return(refToBuiltinFromToken(B_IT, p->b.builtinlit.whichType));
  980.       /* break; */
  981.     case P_INTLIT:
  982.       return(refToBuiltin(B_INSTCT, INTEGERINDEX));
  983.       /* break; */
  984.     case P_BOOLLIT:
  985.       return(refToBuiltin(B_INSTCT, BOOLEANINDEX));
  986.       /* break; */
  987.     case P_STRINGLIT:
  988.       return(refToBuiltin(B_INSTCT, STRINGINDEX));
  989.       /* break; */
  990.     case P_INVOC:
  991.       return(resolveOIDToCTOrAT(p->b.invoc.resultTypeOID));
  992.       /* break; */
  993.     case P_ATLIT:
  994.       return(refToBuiltin(B_INSTCT, SIGNATUREINDEX));
  995.       /* break; */
  996.     case P_GLOBALREF:
  997.       resolveGlobal(p, (ValuePtr) NULL);
  998.       return(getBestInfoFromExpression(p->b.globalref.value));
  999.       /* break; */
  1000.     case P_OBLIT:
  1001.       return(p);
  1002.       /* break; */
  1003.     case P_SYMREF:
  1004.       st = ST_Fetch(p->b.symref.symbol);
  1005.       if (st->value.CTinfo != NULL)
  1006.     return(resolveToCTOrAT(st->value.CTinfo));
  1007.       else
  1008.     return(resolveToCTOrAT(st->value.ATinfo));
  1009.       /* break; */
  1010.     default:
  1011.       assert(FALSE);
  1012.       /*NOTREACHED*/
  1013.       /* break; */
  1014.   }
  1015. }
  1016.  
  1017. OID getCodeID(p)
  1018. NodePtr p;
  1019. {
  1020.   NodePtr q;
  1021.   p = GETVALUE(p);
  1022.   if (p->tag == P_OBLIT) {
  1023.     return(getCodeOID(p));
  1024.   } else if (p->tag == P_BUILTINLIT) {
  1025.     q = refToBuiltinFromToken(B_INSTAT, p->b.builtinlit.whichType);
  1026.     q = resolveOIDToCTOrAT(q->b.atlit.id);
  1027.     assert(q->tag == P_OBLIT);
  1028.     return(getCodeOID(q));
  1029.   } else if (p->tag == P_ATLIT) {
  1030.     q = resolveOIDToCTOrAT(p->b.atlit.id);
  1031.     assert(q->tag == P_OBLIT);
  1032.     return(getCodeOID(q));
  1033.   } else {
  1034.     assert(FALSE);
  1035.     /*NOTREACHED*/
  1036.   }
  1037. }
  1038.  
  1039.  
  1040. OID getID(p)
  1041. NodePtr p;
  1042. {
  1043.   return(GETVALUE(p)->b.oblit.id);
  1044. }
  1045.  
  1046. NodePtr getValue(p)
  1047. NodePtr p;
  1048. {
  1049.   if (p->tag == P_GLOBALREF) {
  1050.     resolveGlobal(p, (ValuePtr) NULL);
  1051.     p = p->b.globalref.value;
  1052.   }
  1053.   assert(p->tag == P_ATLIT || p->tag == P_OBLIT);
  1054.   return(p);
  1055. }
  1056.  
  1057. DD buildAbCon(ATID, CTID)
  1058. OID ATID, CTID;
  1059. {
  1060.   DD result;
  1061.   result.kind = DD_AbCon;
  1062.   setDDConcreteType(result, CTID);
  1063.   setDDAbstractType(result, ATID);
  1064.   return(result);
  1065. }
  1066.  
  1067. DD buildAbConFromObject(p)
  1068. NodePtr p;
  1069. {
  1070.   NodePtr q;
  1071.   q = GETVALUE(p->b.oblit.myat);
  1072.   assert(q->tag == P_ATLIT);
  1073.   return(buildAbCon(q->b.atlit.id, getCodeOID(p)));
  1074. }
  1075.  
  1076. DD buildRegisterDD(registerNumber)
  1077. int registerNumber;
  1078. {
  1079.   DD d;
  1080.   d = nullDD;
  1081.   d.kind = DD_Address;
  1082.   d.value.address = nullAddress;
  1083.   d.value.address.base = Register;
  1084.   d.value.address.offset = registerNumber;
  1085.   if (registerNumber < 0) {
  1086.     implementationBug("Out of temporary registers");
  1087.   } else if (registerNumber < 4) {
  1088.     d.value.address.baseIsTemporary = TRUE;
  1089.     ensureAllocated(registerNumber, 1);
  1090.   }
  1091.   return(d);
  1092. }
  1093.  
  1094. DD buildRegisterDDNC(registerNumber)
  1095. int registerNumber;
  1096. {
  1097.   DD d;
  1098.   d = nullDD;
  1099.   d.kind = DD_Address;
  1100.   d.value.address = nullAddress;
  1101.   d.value.address.base = Register;
  1102.   d.value.address.offset = registerNumber;
  1103.   setDDAbstractType(d, OIDOfBuiltin(B_INSTAT, INTEGERINDEX));
  1104.   return(d);
  1105. }
  1106.  
  1107. DD buildAddressDD(regNo, offset)
  1108. int regNo, offset;
  1109. {
  1110.   DD d;
  1111.   d = nullDD;
  1112.   d.kind = DD_Address;
  1113.   d.value.address.base = regNo;
  1114.   d.value.address.offset = offset;
  1115.   setDDAbstractType(d, OIDOfBuiltin(B_INSTAT, INTEGERINDEX));
  1116.   return(d);
  1117. }
  1118.  
  1119. DD buildLabelDD(labelNumber)
  1120. int labelNumber;
  1121. {
  1122.   DD d;
  1123.   d = nullDD;
  1124.   d.kind = DD_Label;
  1125.   d.value.label = labelNumber;
  1126.   return(d);
  1127. }
  1128.  
  1129. DD buildManifestDD(value)
  1130. int value;
  1131. {
  1132.   DD d;
  1133.   d = nullDD;
  1134.   d.kind = DD_Manifest;
  1135.   d.value.manifest = value;
  1136.   return(d);
  1137. }
  1138.  
  1139. DD buildConCon(index)
  1140. int index;
  1141. {
  1142.   NodePtr theAbObject;
  1143.   theAbObject = refToBuiltin(B_INSTAT, index);
  1144.   assert(theAbObject->tag == P_ATLIT);
  1145.   if (theAbObject->b.atlit.f.cannotBeConformedTo) {
  1146.     return(buildAbCon(OIDOfBuiltin(B_INSTAT, index),
  1147.       OIDOfBuiltin(B_INSTCT, index)));
  1148.   } else {
  1149.     return(buildAbCon(OIDOfBuiltin(B_INSTCT, index),
  1150.       OIDOfBuiltin(B_INSTCT, index)));
  1151.   }
  1152. }
  1153.  
  1154. DD increaseIndirection(d)
  1155. DD d;
  1156. {
  1157.   assert(d.kind == DD_Address);
  1158.   assert(d.value.address.base == Register);
  1159.   d.value.address.base = d.value.address.offset;
  1160.   d.value.address.offset = 0;
  1161.   return(d);
  1162. }
  1163.  
  1164. void freeDD(d)
  1165. DD d;
  1166. {
  1167.   if (d.kind == DD_Address) {
  1168.     if (d.value.address.baseIsTemporary) {
  1169.       if (d.value.address.base == Register) {
  1170.     freeReg((unsigned)d.value.address.offset, 1);
  1171.       } else if (d.value.address.base == regs_l) {
  1172.     /* this really means free the temp stack storage */
  1173.     TS_Free(d.value.address.offset);
  1174.       } else {
  1175.     freeReg(d.value.address.base, 1);
  1176.       }
  1177.     }
  1178.     if (d.value.address.indexIsTemporary) {
  1179.       freeReg(d.value.address.indexReg, 1);
  1180.     }
  1181.   }
  1182. }
  1183.  
  1184. #ifdef TRASHOPNUMBERS
  1185. int translateATOpNumberToCTOpNumber(dd, abstractOpNumber)
  1186. DD dd;
  1187. int abstractOpNumber;
  1188. {
  1189.   OID atOID, ctOID, opOID;
  1190.   NodePtr at, ct;
  1191.   register NodePtr p, ops;
  1192.   int stage, concreteOpNumber;
  1193.   Boolean found = FALSE;
  1194.  
  1195.   assert(dd.kind == DD_AbCon);
  1196.   atOID = getDDAbstractType(dd);
  1197.   ctOID = getDDConcreteType(dd);
  1198.   at = resolveOIDToCTOrAT(atOID);
  1199.   ct = resolveOIDToCTOrAT(ctOID);
  1200.   TRACE0(atctsort, 5, "translate at to ct op number:");
  1201.   TRACE3(atctsort, 5, "at = %s ct = %s number = %d", ATName(at), ATName(ct),
  1202.     abstractOpNumber);
  1203.   if (at->tag == P_OBLIT) {
  1204.     /*
  1205.      * We know the concrete type given the abstract type, so we have the
  1206.      * right operation number already.
  1207.      */
  1208.     TRACE0(atctsort, 7, "Know ct");
  1209.     concreteOpNumber = abstractOpNumber;
  1210.   } else {
  1211.     assert(at->tag == P_ATLIT);
  1212.     assert(ct->tag == P_OBLIT);
  1213.     p = at->b.atlit.ops;
  1214.     assert(isASequence(p));
  1215.     assert(abstractOpNumber >= 0 && abstractOpNumber < Sequence_Length(p));
  1216.     p = p->b.children[abstractOpNumber];
  1217.     assert(p->tag == P_OPSIG);
  1218.     TRACE1(atctsort, 7, "Operation name = %s", SigName(p));
  1219.     p = p->b.opsig.name;
  1220.     assert(p->tag == P_OPNAME);
  1221.     opOID = p->b.opname.id;
  1222.     for (stage = 0; stage < 2 && !found; stage++) {
  1223.       if (stage == 0) {
  1224.     ops = ct->b.oblit.monitor;
  1225.     if (ops != NULL) {
  1226.       assert(ops->tag == P_MONITOR);
  1227.       ops = ops->b.monitor.ops;
  1228.     }
  1229.       } else if (stage == 1) {
  1230.     ops = ct->b.oblit.ops;
  1231.       }
  1232.       Sequence_For(p, ops)
  1233.     assert(p->tag == P_OPDEF);
  1234.     concreteOpNumber = p->b.opdef.opNumber;
  1235.     p = p->b.opdef.sig;
  1236.     assert(p->tag == P_OPSIG);
  1237.     p = p->b.opsig.name;
  1238.     assert(p->tag == P_OPNAME);
  1239.     if (opOID == p->b.opname.id) {
  1240.       found = TRUE;
  1241.       break;
  1242.     }
  1243.       Sequence_Next
  1244.     }
  1245.     assert(found);
  1246.   }
  1247.   TRACE1(atctsort, 5, "returning %d", concreteOpNumber);
  1248.   return(concreteOpNumber);
  1249. }
  1250. #endif
  1251.  
  1252. NodePtr getCTInfo(st)
  1253. register Symbol st;
  1254. {
  1255.   register NodePtr ct;
  1256.   if (st->value.CTinfo != NULL) {
  1257.     ct = st->value.CTinfo;
  1258.   } else {
  1259.     ct = resolveToCTOrAT(st->value.ATinfo);
  1260.     if (ct->tag != P_OBLIT) {
  1261.       ct = NULL;
  1262.     } else {
  1263.       st->value.CTinfo = ct;
  1264.     }
  1265.   }
  1266.   if (ct != NULL) ct = GETVALUE(ct);
  1267.   return(ct);
  1268. }
  1269.  
  1270. NodePtr getBestInfoFromAbCon(d)
  1271. DD d;
  1272. {
  1273.   OID ctoid;
  1274.   NodePtr ct;
  1275.   if (d.kind == DD_AbCon) {
  1276.     ctoid = getDDConcreteType(d);
  1277.     ct = OTLookup(ctoid);
  1278.     assert(ct != NN);
  1279.     assert(ct->tag == P_OBLIT);
  1280.   } else {
  1281.     ctoid = getDDAbstractType(d);
  1282.     ct = resolveOIDToCTOrAT(ctoid);
  1283.     assert(ct->tag == P_ATLIT || ct->tag == P_OBLIT);
  1284.   }
  1285.   return(ct);
  1286. }
  1287.  
  1288. NodePtr ATCTOIDToCTPtr(atoid, ctoid)
  1289. OID atoid, ctoid;
  1290. {
  1291.   NodePtr ct;
  1292.   if (ctoid != 0) {
  1293.     ct = resolveOIDToCTOrAT(ctoid);
  1294.   } else {
  1295.     ct = resolveOIDToCTOrAT(atoid);
  1296.   }
  1297.   return(ct);
  1298. }
  1299.  
  1300. NodePtr getConcreteTypeFromAbCon(d)
  1301. DD d;
  1302. {
  1303.   OID ctoid;
  1304.   NodePtr ct;
  1305.   assert(d.kind == DD_AbCon);
  1306.   ctoid = getDDConcreteType(d);
  1307.   ct = OTLookup(ctoid);
  1308.   assert(ct != NN);
  1309.   return(ct);
  1310. }
  1311.  
  1312. /*
  1313.  * This one returns the symbol of the result of getelement on the
  1314.  * given object constructor.
  1315.  */
  1316. Symbol getElementTypeSymbol(ct)
  1317. NodePtr ct;
  1318. {
  1319.   register NodePtr p;
  1320.   Symbol elementTypeSymbol;
  1321.   char *getelementname = "getelement";
  1322.  
  1323.   assert(ct->tag == P_OBLIT);
  1324.   p = Construct(P_OPNAME, 0);
  1325.   p->b.opname.ident = Ident_Lookup(getelementname, strlen(getelementname));
  1326.   p->b.opname.id = ON_Translate(getelementname);  
  1327.   p = findObjectOperation(ct, p);
  1328.   assert(p->tag == P_OPDEF);
  1329.   p = p->b.opdef.sig;
  1330.   assert(p->tag == P_OPSIG);
  1331.   p = p->b.opsig.results->b.children[0]->b.param.sym;
  1332.   assert(p != NULL);
  1333.   assert(p->tag == P_SYMDEF);
  1334.   elementTypeSymbol = ST_Fetch(p->b.symdef.symbol);
  1335.   return(elementTypeSymbol);
  1336. }
  1337.  
  1338. int getSymbolSize(st)
  1339. Symbol st;
  1340. {
  1341.   int size = -1;
  1342.   AllocateKind ak;
  1343.   
  1344.   ATCTToSizeAndKind(st->value.ATinfo, st->value.CTinfo, st->isAttached, 
  1345.     &size, &ak);
  1346.   assert(size != -1);
  1347.   return(size);
  1348. }
  1349.   
  1350. Brand oidToBrand(atoid)
  1351. OID atoid;
  1352. {
  1353.   switch (atoid) {
  1354.     case OIDOfBuiltin(B_INSTAT, BOOLEANINDEX):
  1355.     case OIDOfBuiltin(B_INSTAT, REALINDEX):
  1356.     case OIDOfBuiltin(B_INSTAT, CHARACTERINDEX):
  1357.     case OIDOfBuiltin(B_INSTAT, INTEGERINDEX):
  1358.     case OIDOfBuiltin(B_INSTCT, BOOLEANINDEX):
  1359.     case OIDOfBuiltin(B_INSTCT, REALINDEX):
  1360.     case OIDOfBuiltin(B_INSTCT, CHARACTERINDEX):
  1361.     case OIDOfBuiltin(B_INSTCT, INTEGERINDEX):
  1362.       return(DataBrand);
  1363.     default:
  1364.       return(ODPBrand);
  1365.   }
  1366. }
  1367.  
  1368. Brand abConToBrand(d)
  1369. DD d;
  1370. {
  1371.   OID atoid;
  1372.   atoid = getDDAbstractType(d);
  1373.   return(oidToBrand(atoid));
  1374. }
  1375.  
  1376. void HSPush(p, startlabel, fhlabel, belabel, loopexitlabel, parent)
  1377. NodePtr p;
  1378. int startlabel, fhlabel, belabel, loopexitlabel;
  1379. BEntryPtr parent;
  1380. {
  1381.   register HSEntryPtr np;
  1382.   TRACE4(handler, 1, "Push: start %d fh %d be %d parent %x", startlabel,
  1383.     fhlabel, belabel, parent);
  1384.   np = (HSEntryPtr) malloc(sizeof(HSEntry));
  1385.   np->p = p;
  1386.   np->startlabel = startlabel;
  1387.   np->fhlabel = fhlabel;
  1388.   np->belabel = belabel;
  1389.   np->loopexitlabel = loopexitlabel;
  1390.   np->parent = parent;
  1391.   np->next = HSStackTop;
  1392.   HSStackTop = np;
  1393. }
  1394.  
  1395. void HSDump()
  1396. {
  1397.   HSEntryPtr p;
  1398.   NodePtr handler;
  1399.   Variable kernObject;
  1400.   Symbol st;
  1401.   int endlabel;
  1402.   
  1403.   while (HSStackTop != NULL) {
  1404.     p = HSStackTop;
  1405.     HSStackTop = HSStackTop->next;
  1406.     handler = p->p;
  1407.     TRACE4(handler, 1, "HSDump: start %d fh %d be %d parent %x", p->startlabel,
  1408.       p->fhlabel, p->belabel, p->parent);
  1409.     assert(loops == NULL);
  1410.     if (p->loopexitlabel != 0) {
  1411.       loops = (LoopRecordPtr) malloc(sizeof(LoopRecord));
  1412.       loops->label = p->loopexitlabel;
  1413.       loops->enclosing = NULL;
  1414.     }
  1415. #ifdef vax
  1416.     emit("\t.byte\t0\n");
  1417. #endif
  1418. #ifdef sun
  1419.     emit("\t.word\t0\n");
  1420. #endif
  1421.     endlabel = nextLabelNumber++;
  1422.     emit("L_%d:\n", p->startlabel);
  1423.     IFOPTION(comment, 1)
  1424.        Comment("\t\t\t\t%s handler start",
  1425.      handler->tag == P_UNAVAILABLEHANDLER ? "unavailable" : "failure");
  1426.     TS_fixSPForHandler();
  1427.     if (handler->tag == P_UNAVAILABLEHANDLER) {
  1428.       TRACE0(handler, 1, "unavailable handler");
  1429.       BStackTop = p->parent;
  1430.       TRACE1(handler, 1, "Popping stack to %x", BStackTop);
  1431.       if (handler->b.unavailablehandler.decl != NULL) {
  1432.     lineNumberComment(handler->b.unavailablehandler.decl);
  1433.     st = ST_Fetch(handler->b.unavailablehandler.decl->b.vardecl.sym->b.symdef.symbol);
  1434.     /* TODO: the run-time type check */
  1435.     vPushVariable(st);
  1436.     claimReg(regs_arg1, 2, VariableBrand);
  1437.     kernObject.data = buildRegisterDD(regs_arg1);
  1438.     kernObject.abCon = nextAddress(kernObject.data);
  1439.     vPush(kernObject);
  1440.     vGenerateAssign();
  1441.       }
  1442.       TRACE0(handler, 1, "generating handler");
  1443.       generate(handler->b.unavailablehandler.body);
  1444.       TRACE2(handler, 1, "add to failure code %d handler %d", endlabel,
  1445.     p->fhlabel);
  1446.       addToIPMap(&failureHandlerMap, endlabel, p->fhlabel, 0);
  1447.       TRACE0(handler, 1, "Setting unavailable of stack top to -1");
  1448.       BStackTop->uhlabel = -1;
  1449.     } else if (handler->tag == P_FAILUREHANDLER) {
  1450.       TRACE0(handler, 1, "failure handler");
  1451.       BStackTop = p->parent;
  1452.       TRACE1(handler, 1, "Popping stack to %x", BStackTop);
  1453.       BStackTop->fhlabel =
  1454.     BStackTop->parent == NULL ? -1 : BStackTop->parent->fhlabel;
  1455.       TRACE1(handler, 1, "Setting failure handler of stack top to %d",
  1456.     BStackTop->fhlabel);
  1457.       generate(handler->b.failurehandler.body);
  1458.     } else {
  1459.       assert(FALSE);
  1460.     }
  1461.     emit("\tj%s\tL_%d\n", JN(ALWAYS), p->belabel);
  1462.     emit("L_%d:\n", endlabel);
  1463.     free((char *) p);
  1464.     if (loops != NULL) {
  1465.       free((char *)loops);
  1466.       loops = NULL;
  1467.     }
  1468.   }
  1469. }
  1470.  
  1471. void blockStart(p)
  1472. NodePtr p;
  1473. {
  1474.   int bslabel, uhlabel, fhlabel, belabel;
  1475.   register BEntryPtr np;
  1476.  
  1477.   bslabel = nextLabelNumber++;
  1478.   belabel = nextLabelNumber++;
  1479.  
  1480.   TRACE2(handler, 1, "Block start bs = %d be = %d", bslabel, belabel);
  1481.   np = (BEntryPtr) malloc(sizeof(BEntry));
  1482.   if (p->b.block.failurehandler != NN) {
  1483.     fhlabel = nextLabelNumber++;
  1484.     TRACE0(handler, 1, "block has failure handler push");
  1485.     HSPush(p->b.block.failurehandler, fhlabel, -1, belabel, 
  1486.       loops == NULL ? 0 : loops->label, np);
  1487.   } else if (BStackTop != NULL) {
  1488.     /*
  1489.      * we propogate the failure statically to the failure handler of
  1490.      * the containing block.
  1491.      */
  1492.     TRACE1(handler, 1, "block has no failure handler propogate to %d",
  1493.       BStackTop->fhlabel);
  1494.     fhlabel = BStackTop->fhlabel;
  1495.   } else {
  1496.     TRACE0(handler, 1, "block has no failure handler, no propogate possible");
  1497.     fhlabel = -1;
  1498.   }
  1499.   if (p->b.block.unavailablehandler != NN) {
  1500.     uhlabel = nextLabelNumber++;
  1501.     TRACE0(handler, 1, "Block has unavailable handler push");
  1502.     HSPush(p->b.block.unavailablehandler, uhlabel, fhlabel, belabel, 
  1503.       loops == NULL ? 0 : loops->label, np);
  1504.   } else {
  1505.     TRACE0(handler, 1, "Block has no unavailable handler");
  1506.     uhlabel = -1;
  1507.   }
  1508.   emit("L_%d:\n", bslabel);
  1509.   if (BStackTop != NULL) {
  1510.     TRACE2(handler, 1, "add to unavailable code %d handler %d", bslabel,
  1511.       BStackTop->uhlabel);
  1512.     addToIPMap(&unavailableHandlerMap, bslabel, BStackTop->uhlabel, 0);
  1513.     TRACE2(handler, 1, "add to failure code %d handler %d", bslabel,
  1514.       BStackTop->fhlabel);
  1515.     addToIPMap(&failureHandlerMap, bslabel, BStackTop->fhlabel, 0);
  1516.   }
  1517.   np->bslabel = bslabel;
  1518.   np->uhlabel = uhlabel;
  1519.   np->fhlabel = fhlabel;
  1520.   np->belabel = belabel;
  1521.   np->parent = BStackTop;
  1522.   BStackTop = np;
  1523.   TRACE5(handler, 1, "Pushing %x on stack: bs %d uh %d  fh %d  be %d", BStackTop,
  1524.     bslabel, uhlabel, fhlabel, belabel);
  1525. }
  1526.  
  1527. void blockEnd()
  1528. {
  1529.   BEntryPtr p = BStackTop;
  1530.   BStackTop = p->parent;
  1531.  
  1532.   TRACE1(handler, 1, "Popping stack to %x", BStackTop);
  1533.   TRACE4(handler, 1, "block end: bs = %d uh = %d fh = %d be = %d",
  1534.     p->bslabel, p->uhlabel, p->fhlabel, p->belabel);
  1535.   emit("L_%d:\n", p->belabel);
  1536.   TRACE2(handler, 1, "add to unavailable code %d handler %d", p->belabel, p->uhlabel);
  1537.   addToIPMap(&unavailableHandlerMap, p->belabel, p->uhlabel, 0);
  1538.   TRACE2(handler, 1, "add to failure code %d handler %d", p->belabel, p->fhlabel);
  1539.   addToIPMap(&failureHandlerMap, p->belabel, p->fhlabel, 0);
  1540. }
  1541.  
  1542. void emitBranchOnBit(bitNumber, clearOrSet, regNo, label)
  1543. int bitNumber;
  1544. char clearOrSet;
  1545. int regNo;
  1546. DD label;
  1547. {
  1548. #ifdef vax
  1549.   if (bitNumber == 0) {
  1550.     emit("\tblb%c\t(%s),", clearOrSet, RN(regNo));
  1551.   } else {
  1552.     emit("\tbb%c\t%c%d,(%s),", clearOrSet, IMMEDIATECHAR, bitNumber, RN(regNo));
  1553.   }
  1554.   writeLabel(label, '\n');
  1555. #endif
  1556. #ifdef sun
  1557.   int bitTstNumber, byteNumber;
  1558.   PSLCondition c;
  1559.   if (bitNumber == 0) {
  1560.     emit("\ttstl\t%s@\n", RN(regNo));
  1561.     c = (clearOrSet == 'c' ? PL : MI);
  1562.   } else {
  1563.     bitTstNumber = 7 - (bitNumber % 8);
  1564.     byteNumber = bitNumber / 8;
  1565.     if (byteNumber == 0) {
  1566.       emit("\tbtst\t%c%d,%s@\n", IMMEDIATECHAR, bitTstNumber, RN(regNo));
  1567.     } else {
  1568.       emit("\tbtst\t%c%d,%s@(%d)\n", IMMEDIATECHAR, bitTstNumber, RN(regNo),
  1569.     byteNumber);
  1570.     }
  1571.     c = (clearOrSet == 'c' ? EQL : NEQ);
  1572.   }
  1573.   emit("\tj%s\t", JN(c));
  1574.   writeLabel(label, '\n');
  1575. #endif
  1576. }
  1577.